/**
 *
 */
package com.et114.modules.org.services;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

//import com.et114.modules.org.vo.GroupRelVo;
import com.et114.components.acegi.AcegiContext;
import com.et114.components.acegi.Constants;
import com.et114.components.acegi.cache.AcegiCacheManager;
import com.et114.core.exception.CheckException;
import com.et114.core.services.impl.BaseServicesImpl;
import com.et114.core.utility.GetterUtil;
import com.et114.core.utility.StringPool;
import com.et114.modules.org.dao.AclDAO;
import com.et114.modules.org.dao.GroupDao;
import com.et114.modules.org.dao.RoleDAO;
import com.et114.modules.org.dao.TitleDAO;
import com.et114.modules.org.dao.UserDAO;
import com.et114.modules.org.vo.FuncComponentVo;
import com.et114.modules.org.vo.FuncRoleRelVo;
import com.et114.modules.org.vo.FunctionVo;
import com.et114.modules.org.vo.GroupVo;
import com.et114.modules.org.vo.RoleVo;
import com.et114.modules.org.vo.UserVo;
import com.et114.modules.system.dictionary.DictionaryCache;
import com.et114.modules.system.dictionary.vo.BizOption;

import net.sf.ehcache.CacheException;


/**
 * @author guanhw
 */
public class RoleManager extends BaseServicesImpl  {
	private RoleDAO roleDAO ;
	private AclDAO aclDAO ;
	private UserDAO userDAO ;
	private TitleDAO titleDAO ; 
	private GroupDao groupDAO ; 

	public void setRoleDAO ( RoleDAO roleDAO ) {
		this.roleDAO = roleDAO;
	}

    public void setAclDAO ( AclDAO aclDAO ) {
        this.aclDAO = aclDAO;
    }
	public void setUserDAO ( UserDAO userDAO ) {
		this.userDAO = userDAO;
	}
   
	public void setTitleDAO ( TitleDAO titleDAO ) {
		this.titleDAO = titleDAO;
	}

	public void setGroupDAO ( GroupDao groupDAO ) {
		this.groupDAO = groupDAO;
	}

	public List getRoles( ) throws CheckException {
		return roleDAO.getRoles ( new RoleVo() ) ;
	}

	public List getRoles( byte roleType )   throws CheckException {
		RoleVo role =  new RoleVo() ; role.setRoleType ( roleType ) ;
		return roleDAO.getRoles ( role ) ;
	}

	public List getTitlesByRole( RoleVo rp )  throws CheckException {
		return roleDAO.getTitlesByRole( rp ) ;
	}

	public List getTitlesByRoleById( Long roleId )  throws CheckException {
		RoleVo role = new RoleVo();
		role.setRoleId ( roleId );
		return getTitlesByRole( role ) ;
	}


	public List getFunctionsByRoleId( Long roleId ) throws CheckException {
		return roleDAO.getFunctionsByRoleId( roleId ) ;
	}

	public List getFunctionCompsByRoleId( Long roleId ) throws CheckException {
		return roleDAO.getFunctionCompsByRoleId( roleId ) ;
	}
	
	public List getRolesByGreaterType( byte roleType ) throws CheckException {
		return roleDAO.getRolesByGreaterType( roleType ) ;
	}
	
	/**
	 * roleIds eg. ( 'admin' , 'user' )
	 * @param roleIds
	 * @return
	 * @throws CheckException
	 */
	public List getFunctionsByRoles ( String  roleIds ) throws CheckException {
		return roleDAO.getFunctionsByRoles( roleIds ) ;
	}

	private List getUsersByRole ( RoleVo rp ) throws CheckException {
		return roleDAO.getUsersByRole( rp ) ;
	}

	private List getUsersByRoleId( Long roleId ) throws CheckException {
		RoleVo role = new RoleVo();role.setRoleId ( roleId );
		return getUsersByRole( role  ) ;
	}

	public RoleVo getRoleById( Long roleId ) throws CheckException {
		return roleDAO.getRoleById (  roleId ) ;
	}


	public List getLimitRoles( RoleVo role ) throws CheckException {
		return roleDAO.getLimitRoles ( role ) ;
	}

	public Long loadRolesRows( RoleVo role ) throws CheckException {
		return roleDAO.loadRolesRows ( role ) ;
	}

	/**
	 * de
	 * @param role
	 * @param type
	 * @throws CheckException
	 * @throws CacheException
	 */
	public void roleRels( RoleVo role , byte type ) throws CheckException , CacheException {
		//Principal
		if ( type == Constants.PRINCIPAL  || type == 0 ) {
			List users = getUsersByRoleId ( role.getRoleId ( ) ) ;
			role.setUsers ( users )   ;
		}

		//resource
		if ( type == Constants.RESOURCE  || type == 0 ) {
			List urls = getFunctionsByRoleId( role.getRoleId ( ) );
			role.setFunctions ( urls ) ;
			//coms
			List coms = roleDAO.getFunctionCompsByRoleId ( role.getRoleId ( ) ) ;
			role.setFunctionEls ( coms ) ;
		}
	}
	
	/**
	 */
	public  void deleteRole( Long roleId , Long operUser ) throws CheckException , CacheException {
		RoleVo role = getRoleById ( roleId ) ; 
		Object key = role.getRoleId ( ) ; 
		if ( Constants.CACHE_NAME.equals ( AcegiContext.getOrgCacheKey ( ) ) ) 
			key = role.getRoleName ( ) ; 
		
		List users = getUsersByRoleId ( roleId );
		List funcs = getFunctionsByRoleId ( roleId ) ;
		List funccls = getFunctionCompsByRoleId(  roleId ) ;
		
		roleDAO.deleteRole ( roleId , operUser ) ;
		aclDAO.deleteAclByRoleId ( roleId , operUser ) ; 
		userDAO.deleteUserRoleRelByRoleId ( roleId , operUser ) ;
		titleDAO.deleteTitleRoleRelByRoleId ( roleId , operUser ) ;
		groupDAO.deleteGroupRoleRelByRoleId ( roleId , operUser ) ;
		
		//
		FuncRoleRelVo funcRoleRel = new FuncRoleRelVo(  ) ;
		funcRoleRel.setRoleId ( roleId ) ; 
		funcRoleRel.setOperUser ( operUser ) ; 
		OrgFactory.getFunctionManager ( ).deleteFuncRoleRel ( funcRoleRel ) ; 

		for ( Iterator iter = users.iterator ( ) ; iter.hasNext ( ) ; ) {
			UserVo user = ( UserVo ) iter.next ( ) ; 
			//OrgFactory.getUserManager ( ).modifyInCache ( user ) ; //since 1.37
			if ( AcegiCacheManager.getInstansce ( ).getUserDetailsByUserId ( user.getLoginName ( ) ) == null ) {
				logger.warn ( "ALLWAYS:WARN>> cache warn !"  ) ; 
				OrgFactory.getUserManager ( ).modifyInCache (  user ) ;
			}
			else 					
				AcegiCacheManager.getInstansce ( ).modUserAuthorityCache (
						user.getLoginName ( ) , Constants.CACHE_DEL , Constants.AUTH_TYPE_ROLE ,
						new Object [ ] { key } , true );
		}

		for ( Iterator iter = funcs.iterator ( ) ; iter.hasNext ( ) ; ) {
			FunctionVo resource = ( FunctionVo )  iter.next ( ) ;
			//OrgFactory.getFunctionManager ( ).modifyInCache ( func ) ; 
			if ( AcegiCacheManager.getInstansce ( ).getAuthorityFromCache ( resource.getResString ( ) ) == null ) {
				logger.warn ( "ALLWAYS:WARN>> cache warn !"  ) ; 
				OrgFactory.getFunctionManager ( ).modifyInCache (  resource ) ; 
			}
			else 								
				AcegiCacheManager.getInstansce ( ).modResourceAuthorityCache (
						resource.getResString ( ) , Constants.CACHE_DEL ,
						Constants.AUTH_TYPE_ROLE , new Object [ ] { key } );
		}

		for ( Iterator iter = funccls.iterator ( ) ; iter.hasNext ( ) ; ) {
			FuncComponentVo resource = ( FuncComponentVo ) iter.next ( ) ;
			//OrgFactory.getFunctionManager ( ).modifyInCache ( funccomp ) ; 
			if ( AcegiCacheManager.getInstansce ( ).getAuthorityFromCache ( resource.getResString ( ) ) == null ) {
				logger.warn ( "ALLWAYS:WARN>> cache warn !"  ) ; 
				OrgFactory.getFunctionManager ( ).modifyInCache (  resource ) ; 
			}
			else 											
				AcegiCacheManager.getInstansce ( ).modResourceAuthorityCache (
						resource.getResString ( ) , Constants.CACHE_DEL ,
						Constants.AUTH_TYPE_ROLE , new Object [ ] { key } );			
		}
	
	}

	public  void addRole( RoleVo role ) throws CheckException {
		roleDAO.addRole ( role ) ;
	}

	public  void updateRole( RoleVo role ) throws CheckException , CacheException{
		String roleName = roleDAO.getRoleById ( role.getRoleId ( ) ) .getRoleName ( );
		roleDAO.updateRole ( role ) ;
		if ( Constants.CACHE_NAME.equals ( AcegiContext.getOrgCacheKey ( ) ) ) {
			if ( ! roleName .equals ( role.getRoleName ( ) ) ) {
				/*
				roleRels( role , ( byte )0 ) ;
				AcegiCacheManager.getInstansce ( ).modifyRoleInCache ( role ) ;
				*/ //since 1.37
				List users = getUsersByRoleId ( role.getRoleId ( ) );
				List funcs = getFunctionsByRoleId ( role.getRoleId ( ) ) ;
				List funccls = getFunctionCompsByRoleId(  role.getRoleId ( ) ) ;
				for ( Iterator iter = users.iterator ( ) ; iter.hasNext ( ) ; ) {
					UserVo user = ( UserVo ) iter.next ( ) ; 
					//OrgFactory.getUserManager ( ).modifyInCache ( user ) ; //since 1.37
					if ( AcegiCacheManager.getInstansce ( ).getUserDetailsByUserId ( user.getLoginName ( ) ) == null ) {
						logger.warn ( "ALLWAYS:WARN>> cache warn !"  ) ; 
						OrgFactory.getUserManager ( ).modifyInCache (  user ) ;
					}
					else 		
						AcegiCacheManager.getInstansce ( ).modAuthorityCache (
								Constants.PRINCIPAL , user.getLoginName ( ) , roleName , role.getRoleName ( ) ,
								Constants.AUTH_TYPE_ROLE );
				}

				for ( Iterator iter = funcs.iterator ( ) ; iter.hasNext ( ) ; ) {
					FunctionVo resource = ( FunctionVo )  iter.next ( ) ;
					//OrgFactory.getFunctionManager ( ).modifyInCache ( func ) ; 
					if ( AcegiCacheManager.getInstansce ( ).getAuthorityFromCache ( resource.getResString ( ) ) == null ) {
						logger.warn ( "ALLWAYS:WARN>> cache warn !"  ) ; 
						OrgFactory.getFunctionManager ( ).modifyInCache (  resource ) ; 
					}
					else 					
						AcegiCacheManager.getInstansce ( ).modAuthorityCache (
								Constants.RESOURCE , resource.getResString ( ) , roleName , role.getRoleName ( ) ,
								Constants.AUTH_TYPE_ROLE );
				}

				for ( Iterator iter = funccls.iterator ( ) ; iter.hasNext ( ) ; ) {
					FuncComponentVo resource = ( FuncComponentVo ) iter.next ( ) ;
					//OrgFactory.getFunctionManager ( ).modifyInCache ( funccomp ) ; 
					if ( AcegiCacheManager.getInstansce ( ).getAuthorityFromCache ( resource.getResString ( ) ) == null ) {
						logger.warn ( "ALLWAYS:WARN>> cache warn !"  ) ; 
						OrgFactory.getFunctionManager ( ).modifyInCache (  resource ) ; 
					}
					else 										
						AcegiCacheManager.getInstansce ( ).modAuthorityCache (
								Constants.RESOURCE , resource.getResString ( ) , roleName , role.getRoleName ( ) ,
								Constants.AUTH_TYPE_ROLE );
				}
			}
			//update cache
		}
	}
	

	public void updateRole( RoleVo role , String tn  ) throws CheckException , CacheException{
		updateRole( role ) ; 
	}
	
	public Long countRoles ( String roleName ) throws CheckException {
		return roleDAO.countRoles ( roleName );
	}
	
	public BizOption getRoleType( byte roleType ) throws Exception {
		List options = DictionaryCache.getInstance ( ).listBizOptions ( Constants.ROLE_DIC_BIZ_KEY , false )   ;
		for ( java.util.Iterator iter = options.iterator ( ) ; iter.hasNext ( ) ;  ) {
			BizOption bizOption = ( BizOption ) iter.next ( ) ; 
			short roleType_ = GetterUtil.getShort( bizOption.getOptionValue ( ) , Constants.ROLE_TYPE_USER ) ;
			if ( roleType_ == roleType ) return bizOption ; 
		}
		return null ;
	}		
	
	/**
	 * @param roleType 大于
	 * @param eq 是否等于
	 * @throws Exception
	 */
	public List getRoleTypes( byte roleType , boolean eq ) throws Exception {
	    List soptions = new ArrayList( ) ; 
		List options = DictionaryCache.getInstance ( ).listBizOptions ( Constants.ROLE_DIC_BIZ_KEY , false )   ;
		for ( java.util.Iterator iter = options.iterator ( ) ; iter.hasNext ( ) ;  ) {
			BizOption bizOption = ( BizOption ) iter.next ( ) ; 
			short roleType_ = GetterUtil.getShort( bizOption.getOptionValue ( ) , Constants.ROLE_TYPE_USER ) ;
			if (  roleType_ != Constants.ROLE_TYPE_SUPER ) {
				if (roleType_ > roleType  ) soptions.add ( bizOption ) ;
				else if  ( roleType == roleType_ && eq ) soptions.add ( bizOption ) ;;
			}
		}
		return soptions ;
	}	
	
	public List getRoleTypes(  ) throws Exception {
	    List soptions = new ArrayList( ) ; 
		List options = DictionaryCache.getInstance ( ).listBizOptions ( Constants.ROLE_DIC_BIZ_KEY , false )   ;
		for ( java.util.Iterator iter = options.iterator ( ) ; iter.hasNext ( ) ;  ) {
			BizOption bizOption = ( BizOption ) iter.next ( ) ; 
			short roleType_ = GetterUtil.getShort( bizOption.getOptionValue ( ) , Constants.ROLE_TYPE_USER ) ;
			if (  roleType_ != Constants.ROLE_TYPE_SUPER ) {
				soptions.add ( bizOption ) ;
			}
		}
		return soptions ;
	}		
	/**
	 * 
	 * @param roleIds
	 * @return
	 * @throws CheckException
	 */
	public List getGroupsByRoles( String  roleIds ) throws CheckException {
		return roleDAO.getGroupsByRoles ( roleIds );
	}
	
	/**
	 * 递归取角色对应所有机构  map key：grpId value：group
	 * @param roleIds
	 * @return
	 * @throws CheckException
	 */
	public Map getGroupsAnByRoles( String roleIds ) throws CheckException { 
		List groups_ = roleDAO.getGroupRelsByRoles( roleIds ) ; 
		Map map =  OrgFactory.getGroupManager ( ).listToMapKeyGrpId ( groups_  ) ;
		if ( map.size ( ) == 0  ) return  map;
		
		String[ ] grpPaths = new String[ groups_.size ( ) ]  ;
		int count = 0 ; 
		for ( java.util.Iterator iter = groups_.iterator ( ) ; iter.hasNext ( ) ; ) {
			GroupVo group = ( GroupVo ) iter.next ( ) ;
			grpPaths[ count ] = group.getGroupRelVo ( ).getGrpPath ( ) + StringPool.SLE ; 
			count ++ ;
		}
	
		groups_ = groupDAO.getGroupsByPaths ( grpPaths ) ; 
		map.putAll ( OrgFactory.getGroupManager ( ).listToMapKeyGrpId ( groups_  ) ) ;
		return  map ;
	}
	
	

	
	/**
	 * key : grpId ;  value : vo
	 * 递归取角色对应机构根机构
	 * @param roleIds
	 * @return
	 * @throws CheckException
	 */
	public List getRootsGroupsByRolesSorts( Map groups ) throws CheckException { 
		List rootGrps = new ArrayList( ) ; 
		if ( groups == null ) return rootGrps ; 
		for ( java.util.Iterator iter = groups.keySet ( ).iterator ( ) ; iter.hasNext ( ) ; ) {
			Object key = iter.next ( ) ; 
			GroupVo group = ( GroupVo ) groups.get ( key ) ;
			Long fgrpId = group.getFgrpId ( ) ; 
			if ( groups.containsKey ( fgrpId ) )  {
				rootGrps.add ( key ) ; 
			}
		}
		
		for ( java.util.Iterator iter = rootGrps.iterator ( ) ; iter.hasNext ( ) ;  ) {
			groups.remove (  iter.next ( )  ) ; 
		}
		rootGrps.clear ( ) ; 
		rootGrps.addAll ( groups.values ( ) ) ; 
		return rootGrps ;
	}
	
	public List queryRolesByIds ( String [ ] sRoleIds ) throws CheckException {
		Long[] roleIds = new Long[ sRoleIds.length ] ; 
		for ( int i = 0 ; i < roleIds.length ; i ++ ) 
			roleIds[ i ] = Long.valueOf ( sRoleIds[ i ] ) ; 
		RoleVo role = new RoleVo( ) ; 
		role.setRoleIds ( roleIds ) ; 
		return roleDAO.getRoles ( role ) ; 
	}	
	
	public List getUserRelation( RoleVo roleVo ) throws CheckException {
		return roleDAO.getUserRelation ( roleVo );
	}
	
	public Long countUserRelation ( RoleVo roleVo ) throws CheckException {
		return roleDAO.countUserRelation ( roleVo );
	}
	
	public List getTitleRelation( RoleVo role  ) throws CheckException {
		return roleDAO.getTitleRelation ( role );
	}
	
	public int countTitleRelation ( RoleVo roleVo ) throws CheckException {
		return roleDAO.countTitleRelation ( roleVo );
	}
	
	public List getGroupRelation( Long  roleId ) throws CheckException {
		return roleDAO.getGroupRelation ( roleId );
	}
	
	public int countGroupRelation ( Long roleId ) throws CheckException {
		return roleDAO.countGroupRelation ( roleId );
	}	
	
	public List getFuncPaths( Long  roleId ) throws CheckException {
		return roleDAO.getFuncPaths ( roleId );
	}
	
	public List getFuncRelation( FunctionVo functionvo ) throws CheckException {
		return roleDAO.getFuncRelation ( functionvo );
	}
	
	public List getComRelation( FuncComponentVo funcComponentVo ) throws CheckException {
		return roleDAO.getComRelation ( funcComponentVo ) ;
	}
	
	
}
